Search Results: "decklin"

24 November 2005

Clint Adams: Musical Personality Disorder

Decklin, MPD looks pretty interesting. I have filed a wishlist bug on vux on the presumption that integrating it with mpd would be peachy keen. Still, mpdscribble is conspiring against me. That it can't get MusicBrainz IDs is a minor irritation. The more significant problem is that it doesn't work at all. For every song, it whines about skipping, like this:
new song detected (Leonard Cohen - Hey, That's No Way to Say Goodbye)
skipping detected, not submitting.
I'm not doing any skipping, and crossfade is set to '0'. I continue to use my happy NIH pseudosolution.

20 November 2005

Matthew Palmer: The Fun Never Stops With Ruby

Well, there's nothing like posting a really rubbish program to your blog to find out the right way to do it. Firstly, Philipp Kern has come up with another, even shorter version than his version I posted in the update to my original Ruby post, this time blowing me away with the strangeness of explicit casts in Ruby. Apparently, casting an input stream to an array produces an array with one-line-per-element, as in this example:
 STDIN.to_a.sort_by rand .each l puts l 
As Philipp warns, however: "Ruby is full of fun and power; one must watch out that the scripts remain readable". For a fairly toy example, this solution is still fairly readable, however I can see hair growing on this thing if your program grows large. Next, Pierre-Charles David showed his qualifications for becoming a co-author of the next edition of the Pickaxe (AKA "Programming Ruby: The Pragmatic Programmers' Guide"), with his example and explanation. He's kindly given permission for me to reproduce his e-mail in it's entireity, since it's too good to chop up:
Here is the shortest and most readable version of your "randomize stdin" script I can think of:
  #!/usr/bin/env ruby
  print ARGF.readlines.sort_by   rand  
 
ARGF is a special variable representing either stdin or, in the case where file names are passed on the command line, the content of these files (think of Perl's <>). ARGF behaves like an IO object (although I think it is not one). In particular, it responds to the #readlines method which splits the receiver's content into lines and returns an array. In other words,
  lines = ARGF.readlines
 
is the idiomatic way of doing
  lines = []
  while line = gets() do
    lines << line
  end
 
in your example. The next part (sort_by) uses a new form of the sort method, which I think is not documented in the Pickaxe. It implements the Schwartzian transform technique. In essence, a random number is associated to each element of the array, which are then sorted based on this index. As a general style remark, note that although Ruby supports "while" and "for x in y" loops, they are rarely used, in favor of iterators and/or higher order methods. For example, to gather all the input lines in an array without using readlines, one might write
  lines = Array.new
  ARGF.each_line    l  lines << l  
 
or
  lines = ARGF.inject([])    lines, l  lines << l  
 
Hope it helps, and welcome to Ruby!
Pierre, your explanation definitely helped, and I hope it helps others too. The third person to help me out is Decklin Foster, through a post in his blog. What particularly caught me about his solution was the neat demonstration of another feature of Ruby which I think I will really learn to love: the ability to dynamically add methods to an existing class. "Aiee!" I hear all the purists scream -- and I can see the potential for severe misuse, too. But, since every good idea seems to get deeply perverted, we may as well have some real useful features to pervert while we're at it. Decklin has the clever idea of adding methods to the Array class that shuffle the elements of the array in a random fashion. His code is beautiful in it's simplicity:
 class Array
    def swap!(a, b)
        self[a], self[b] = self[b], self[a]
        self
    end
    def shuffle!
        each_index do  i 
            j = i + rand(length - i)
            swap!(i, j)
        end
        self
    end
 end
He then goes on to rewrite my bumbling example in probably the most comprehensible manner I've yet seen:
 STDIN.readlines.shuffle!.each    line  puts line  
Decklin writes, "Now that is cool.". I couldn't have put it better myself. My thanks to Philipp, Pierre-Charles, and Decklin, for helping me along the Ruby path. So, two new Ruby Rules for me to live by: Hmm, is it possible that Ruby is nothing more than Functional Programming by Stealth? Aiee!

Next.

Previous.